/*
 * Copyright (C), 2002-2016, 苏宁易购电子商务有限公司
 * FileName: HttpClientUtil.java
 * Author:   admin
 * Date:     2016年1月5日 下午4:01:24
 * Description: //模块目的、功能描述      
 * History: //修改记录
 * <author>      <time>      <version>    <desc>
 * 修改人姓名             修改时间            版本号                  描述
 */
package com.suning.app.snpaasadmin.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.FileEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;

/**
 * 〈一句话功能简述〉<br>
 * 〈功能详细描述〉
 *
 * @author admin
 * @see [相关类/方法]（可选）
 * @since [产品/模块版本] （可选）
 */
public class HttpClientUtil {

    private static int TIMEOUT = 600000;

    public static HttpClientResponse doGet(String url, Map<String, String> params, Map<String, String> headers,
            HttpHost host, HttpContext context) throws Exception {
        HttpGet httpGet = null;
        CloseableHttpResponse response = null;
        CloseableHttpClient httpClient = null;
        try {
            httpClient = ClusterClientUtil.createHttpsClient();

            // 设置请求和传输超时时间
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(TIMEOUT).setConnectTimeout(TIMEOUT)
                    .build();
            httpGet = new HttpGet(url);
            setHeaders(httpGet, headers);
            httpGet.setConfig(requestConfig);

            response = httpClient.execute(host, httpGet, context);
            HttpEntity resentity = response.getEntity();
            String content = null;
            if (resentity != null) {
                content = EntityUtils.toString(resentity, "UTF-8");
            }
            return new HttpClientResponse(response.getStatusLine().getStatusCode(), content);
        } catch (Exception e) {
            throw e;
        } finally {
            if (httpGet != null) {
                httpGet.abort();
            }
            httpClient.close();
        }
    }

    public static HttpClientResponse doPost(String url, Map<String, String> params, Map<String, String> headers,
            HttpHost host, HttpContext context) throws Exception {
        HttpPost httpPost = null;
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        try {
            httpClient = ClusterClientUtil.createHttpsClient();

            // 设置请求和传输超时时间
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(TIMEOUT).setConnectTimeout(TIMEOUT)
                    .build();
            httpPost = new HttpPost(url);
            httpPost.setConfig(requestConfig);
            setHeaders(httpPost, headers);
            List<NameValuePair> requestParams = new ArrayList<NameValuePair>();
            // 设置Http Post数据
            if (params != null) {
                for (Map.Entry<String, String> entry : params.entrySet()) {
                    requestParams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
                }
            }
            HttpEntity entity = new UrlEncodedFormEntity(requestParams, "utf-8");
            httpPost.setEntity(entity);
            response = httpClient.execute(host, httpPost, context);
            HttpEntity resentity = response.getEntity();
            String content = null;
            if (resentity != null) {
                content = EntityUtils.toString(resentity, "UTF-8");
            }
            return new HttpClientResponse(response.getStatusLine().getStatusCode(), content);
        } catch (Exception e) {
            throw e;
        } finally {
            httpPost.abort();
        }
    }

    private static void setHeaders(HttpRequestBase method, Map<String, String> headers) {
        if (headers == null) {
            return;
        }
        for (Map.Entry<String, String> entry : headers.entrySet()) {
            method.addHeader(entry.getKey(), entry.getValue());
        }
    }

    public static File doGetDownload(String url, Map<String, String> params, Map<String, String> headers,
            HttpHost host, HttpContext context, String deployName) throws Exception {
        HttpGet httpGet = null;
        CloseableHttpResponse response = null;
        CloseableHttpClient httpclient = null;
        File file = null;
        try {
            httpclient = ClusterClientUtil.createHttpsClient();

            // 设置请求和传输超时时间
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(TIMEOUT).setConnectTimeout(TIMEOUT)
                    .build();
            httpGet = new HttpGet(url);
            setHeaders(httpGet, headers);
            httpGet.setConfig(requestConfig);

            response = httpclient.execute(host, httpGet, context);
            HttpEntity resentity = response.getEntity();

            Format format = new SimpleDateFormat("yyyyMMddHHmmSS");
            file = new File("/opt/logs/" + format.format(new Date()) + deployName + ".tar");

            OutputStream os = new FileOutputStream(file);
            resentity.writeTo(os);
            os.close();
            return file;
        } catch (Exception e) {
            throw e;
        } finally {
            if (httpGet != null) {
                httpGet.abort();
            }
            httpclient.close();
        }
    }

    public static HttpClientResponse doPostWithFile(String url, File file, HttpHost host, HttpContext context)
            throws Exception {
        HttpPost httpPost = null;
        CloseableHttpClient httpclient = null;
        CloseableHttpResponse response = null;
        try {
            httpclient = ClusterClientUtil.createHttpsClient();
            httpPost = new HttpPost(url);
            httpPost.addHeader("Content-Type", "application/x-compressed");
            FileEntity se = new FileEntity(file);
            httpPost.setEntity(se);
            response = httpclient.execute(host, httpPost, context);
            HttpEntity resentity = response.getEntity();
            String content = null;
            if (resentity != null) {
                content = EntityUtils.toString(resentity, "UTF-8");
            }
            return new HttpClientResponse(response.getStatusLine().getStatusCode(), content);
        } catch (Exception e) {
            throw e;
        } finally {
            httpclient.close();
            if (httpPost != null) {
                httpPost.abort();
            }
        }
    }

    public static CloseableHttpResponse doPostWithBodyData(String url, String data, HttpHost host, HttpContext context)
            throws Exception {
        HttpPost httpPost = null;
        CloseableHttpClient httpclient = null;
        CloseableHttpResponse response = null;
        try {
            httpclient = ClusterClientUtil.createHttpsClient();
            httpPost = new HttpPost(url);
            httpPost.addHeader("Content-Type", "text/yaml");
            StringEntity se = new StringEntity(data);
            httpPost.setEntity(se);
            response = httpclient.execute(host, httpPost, context);
            return response;
        } catch (Exception e) {
            throw e;
        } finally {
            httpclient.close();
            if (httpPost != null) {
                httpPost.abort();
            }
        }
    }

    public static CloseableHttpResponse doGetDeployLog(String url, Map<String, String> params,
            Map<String, String> headers, HttpHost host, HttpContext context) throws Exception {
        HttpGet httpGet = null;
        CloseableHttpResponse response = null;
        CloseableHttpClient httpclient = null;
        try {
            httpclient = ClusterClientUtil.createHttpsClient();

            // 设置请求和传输超时时间
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(TIMEOUT).setConnectTimeout(TIMEOUT)
                    .build();
            httpGet = new HttpGet(url);
            setHeaders(httpGet, headers);
            httpGet.setConfig(requestConfig);

            response = httpclient.execute(host, httpGet, context);
            return response;
        } catch (Exception e) {
            throw e;
        } finally {
            if (httpGet != null) {
                httpGet.abort();
            }
            httpclient.close();
        }
    }

    /**
     * contentType:application/x-www-form-urlencoded
     * 
     * @param url
     * @param params
     * @param headers
     * @return
     * @throws Exception
     */
    public static HttpClientResponse doPostWithCC(String url, Map<String, String> params, Map<String, String> headers)
            throws Exception {
        HttpPost httpPost = null;
        CloseableHttpClient httpClient = null;
        HttpResponse response = null;
        try {
            httpClient = ClusterClientUtil.createHttpsClient();

            // 设置请求和传输超时时间
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(TIMEOUT).setConnectTimeout(TIMEOUT)
                    .build();
            httpPost = new HttpPost(url);
            httpPost.setConfig(requestConfig);
            setHeaders(httpPost, headers);
            List<NameValuePair> requestParams = new ArrayList<NameValuePair>();
            // 设置Http Post数据
            if (params != null) {
                for (Map.Entry<String, String> entry : params.entrySet()) {
                    requestParams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
                }
            }
            HttpEntity entity = new UrlEncodedFormEntity(requestParams, "utf-8");
            httpPost.setEntity(entity);
            response = httpClient.execute(httpPost);
            HttpEntity resentity = response.getEntity();
            String content = null;
            if (resentity != null) {
                content = EntityUtils.toString(resentity, "UTF-8");
            }
            return new HttpClientResponse(response.getStatusLine().getStatusCode(), content);
        } catch (Exception e) {
            throw e;
        } finally {
            httpPost.abort();
        }
    }

    /**
     * content-type:application/josn
     * 
     * @param url
     * @param params
     * @param headers
     * @return
     * @throws Exception
     */
    public static HttpClientResponse doPostWithJsonType(String url, Map<String, String> params,
            Map<String, String> headers) throws Exception {
        HttpPost httpPost = null;
        CloseableHttpClient httpclient = null;
        CloseableHttpResponse response = null;
        try {
            httpclient = ClusterClientUtil.createHttpsClient();

            // 设置请求和传输超时时间
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(TIMEOUT).setConnectTimeout(TIMEOUT)
                    .build();
            httpPost = new HttpPost(url);
            httpPost.setConfig(requestConfig);
            setHeaders(httpPost, headers);
            if (params != null) {
                HttpEntity entity = new StringEntity(JsonUtil.convertToJson(params), "utf-8");
                httpPost.setEntity(entity);
            }
            response = httpclient.execute(httpPost);
            HttpEntity resentity = response.getEntity();
            String content = null;
            if (resentity != null) {
                content = EntityUtils.toString(resentity, "UTF-8");
            }
            return new HttpClientResponse(response.getStatusLine().getStatusCode(), content);
        } catch (Exception e) {
            throw e;
        } finally {
            httpPost.abort();
        }
    }

    public static HttpClientResponse doPut(String url, Map<String, Object> params, Map<String, String> headers)
            throws Exception {
        CloseableHttpClient httpClient = null;
        HttpPut httpPut = null;
        CloseableHttpResponse response = null;
        try {
            httpClient = HttpClients.createDefault();

            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(TIMEOUT).setConnectTimeout(TIMEOUT)
                    .build();
            httpPut = new HttpPut(url);
            httpPut.setConfig(requestConfig);
            setHeaders(httpPut, headers);
            if (params != null) {
                HttpEntity entity = new StringEntity(JsonUtil.convertToJson(params), "utf-8");
                httpPut.setEntity(entity);
            }
            response = httpClient.execute(httpPut);
            HttpEntity resentity = response.getEntity();
            String content = null;
            if (resentity != null) {
                content = EntityUtils.toString(resentity, "UTF-8");
            }
            return new HttpClientResponse(response.getStatusLine().getStatusCode(), content);
        } catch (Exception e) {
            throw e;
        } finally {
            httpPut.abort();
        }
    }

    public static CloseableHttpResponse doPutWithComponent(String url, HttpHost host, HttpContext context, String data)
            throws Exception {
        CloseableHttpClient httpClient = null;
        HttpPut httpPut = null;
        CloseableHttpResponse response = null;
        try {
            httpClient = ClusterClientUtil.createHttpsClient();

            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(TIMEOUT).setConnectTimeout(TIMEOUT)
                    .build();
            httpPut = new HttpPut(url);
            httpPut.setConfig(requestConfig);
            httpPut.addHeader("Content-Type", "text/yaml");
            StringEntity se = new StringEntity(data);
            httpPut.setEntity(se);
            response = httpClient.execute(host, httpPut, context);
            return response;
        } catch (Exception e) {
            throw e;
        } finally {
            httpPut.abort();
        }
    }

    public static HttpClientResponse doGet(String url, Map<String, String> params, Map<String, String> headers)
            throws Exception {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        HttpGet httpGet = null;
        try {
            httpClient = ClusterClientUtil.createHttpsClient();
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(TIMEOUT).setConnectTimeout(TIMEOUT)
                    .build();
            httpGet = new HttpGet(url);
            httpGet.setConfig(requestConfig);
            setHeaders(httpGet, headers);
            response = httpClient.execute(httpGet);
            HttpEntity resentity = response.getEntity();
            String content = null;
            if (resentity != null) {
                content = EntityUtils.toString(resentity, "UTF-8");
            }
            return new HttpClientResponse(response.getStatusLine().getStatusCode(), content);
        } catch (Exception e) {
            throw e;
        } finally {
            if (httpGet != null) {
                httpGet.abort();
            }
        }

    }

    public static HttpClientResponse doDelete(String url, Map<String, String> params, Map<String, String> headers,
            HttpHost host, HttpContext context) throws Exception {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        HttpDelete httpDelete = null;
        try {
            httpClient = ClusterClientUtil.createHttpsClient();
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(TIMEOUT).setConnectTimeout(TIMEOUT)
                    .build();
            httpDelete = new HttpDelete(url);
            httpDelete.setConfig(requestConfig);
            setHeaders(httpDelete, headers);
            response = httpClient.execute(host, httpDelete, context);
            HttpEntity resentity = response.getEntity();
            String content = null;
            if (resentity != null) {
                content = EntityUtils.toString(resentity, "UTF-8");
            }
            return new HttpClientResponse(response.getStatusLine().getStatusCode(), content);
        } catch (Exception e) {
            throw e;
        } finally {
            if (httpClient != null) {
                httpClient.close();
            }
            if (httpDelete != null) {
                httpDelete.abort();
            }
        }
    }

    public static String sendPostToYunInterface(String url, String param) {
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);

            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += "" + line;
            }
        } catch (Exception e) {
            System.out.println("发送POST请求出现异常！" + e);
            e.printStackTrace();
        }
        // 使用finally块来关闭输出流、输入流
        finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return result;
    }

    @SuppressWarnings("static-access")
    public static void disableCertificateValidation(HttpsURLConnection httpsURLConnection) {
        try {
            // Create a trust manager that does not validate certificate chains
            TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return null;
                }

                public void checkClientTrusted(X509Certificate[] certs, String authType) {
                }

                public void checkServerTrusted(X509Certificate[] certs, String authType) {
                }
            } };

            // Install the all-trusting trust manager
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            httpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

            // Create all-trusting host name verifier
            HostnameVerifier allHostsValid = new HostnameVerifier() {
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            };

            // Install the all-trusting host verifier
            httpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
    }

    public static HttpClientResponse doDelete(String url, Map<String, String> params, Map<String, String> headers)
            throws Exception {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        HttpDelete httpDelete = null;
        try {
            httpClient = ClusterClientUtil.createHttpsClient();
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(TIMEOUT).setConnectTimeout(TIMEOUT)
                    .build();
            httpDelete = new HttpDelete(url);
            httpDelete.setConfig(requestConfig);
            setHeaders(httpDelete, headers);
            response = httpClient.execute(httpDelete);
            HttpEntity resentity = response.getEntity();
            String content = null;
            if (resentity != null) {
                content = EntityUtils.toString(resentity, "UTF-8");
            }
            return new HttpClientResponse(response.getStatusLine().getStatusCode(), content);
        } catch (Exception e) {
            throw e;
        } finally {
            if (httpClient != null) {
                httpClient.close();
            }
            if (httpDelete != null) {
                httpDelete.abort();
            }
        }
    }

}
